For SaaS and fintech
Transactional email and onboarding journeys for your product.
Transactional email through a Resend-compatible API. Journeys that start when your product sends an event. Broadcasts you say out loud. One domain, one consent model, one log for all of it.

What should we send today?
Say it in a sentence. Linnet writes the email, picks who gets it, and sets the time.
# Your app tells Linnet what happened. curl https://app.linnet.run/v1/events \ -H "Authorization: Bearer $LINNET_API_KEY" \ -d '{"id":"signup-user_123", "name":"user.signed_up", "contact_id":"user_123", "properties":{"plan":"trial"}}' # The journey you approved in chat starts.
// Your app tells Linnet what happened. await fetch("https://app.linnet.run/v1/events", { method: "POST", headers: { Authorization: `Bearer ${process.env.LINNET_API_KEY}` }, body: JSON.stringify({ id: "signup-user_123", name: "user.signed_up", contact_id: "user_123", properties: { plan: "trial" } }) }); // The journey you approved in chat starts.
Same product, two doors. Chat for the people, API and MCP for your code and your AI. An event never grants email permission.
What a product sends
What your product can send.
Transactional email is a request. Everything else is a sentence that comes back as a card.
Moving from Resend or SES
Move from Resend or SES by changing two settings.
Bring your audience with it. Contacts are not a line on the bill. Weighing it up? Resend alternatives, honestly compared, or let us move you by hand, free.
Two settings
# .env RESEND_API_KEY=lnt_live_… RESEND_BASE_URL=https://app.linnet.run # Your code, unchanged await resend.emails.send({ from: "billing@northstar.app", to: user.email, subject: "Your receipt", html });
Same request shape, same response shape. Batch and cancel work the same way.
Bring your audience
curl https://app.linnet.run/v1/contact-imports \
-H "Authorization: Bearer $LINNET_API_KEY" \
-d '{"source_key":"product",
"contacts":[{"source_object_id":"user_123",
"email":"ada@northstar.app",
"consent":{"purpose":"marketing",
"status":"granted"}}]}'
Or upload the export from Resend, Mailchimp, or a CSV. Rows are reconciled one by one, consent included.
Start journeys from events
curl https://app.linnet.run/v1/events \
-H "Authorization: Bearer $LINNET_API_KEY" \
-d '{"id":"trial-day7-user_123",
"name":"trial.day_7_no_project",
"contact_id":"user_123"}'
Send events by user id. The journey you approved in chat picks them up. An event never grants email permission.
Start
Send your first real email today.
Connect your domain, change two settings, say the first sentence.


